Optimized [rand.dist.samp.pconst] and several bug fixes in other distributions git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@104478 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/random b/include/random index c5f9b17..1a680ff 100644 --- a/include/random +++ b/include/random
@@ -3642,7 +3642,8 @@ const uniform_real_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); return __os << __x.a() << __sp << __x.b(); @@ -3736,7 +3737,8 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const bernoulli_distribution& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); return __os << __x.p(); @@ -3880,7 +3882,8 @@ const binomial_distribution<_IntType>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); return __os << __x.t() << __sp << __x.p(); @@ -3981,7 +3984,8 @@ const exponential_distribution<_RealType>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); return __os << __x.lambda(); } @@ -4116,7 +4120,8 @@ const normal_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); __os << __x.mean() << __sp << __x.stddev() << __sp << __x._V_hot_; @@ -4451,7 +4456,8 @@ const poisson_distribution<_IntType>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); return __os << __x.mean(); } @@ -4542,7 +4548,8 @@ const weibull_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); __os << __x.a() << __sp << __x.b(); @@ -4642,7 +4649,8 @@ const extreme_value_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); __os << __x.a() << __sp << __x.b(); @@ -4795,7 +4803,8 @@ const gamma_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); __os << __x.alpha() << __sp << __x.beta(); @@ -4912,7 +4921,8 @@ const negative_binomial_distribution<_IntType>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); return __os << __x.k() << __sp << __x.p(); @@ -4999,7 +5009,8 @@ const geometric_distribution<_IntType>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); return __os << __x.p(); } @@ -5085,7 +5096,8 @@ const chi_squared_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); __os << __x.n(); return __os; } @@ -5186,7 +5198,8 @@ const cauchy_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); __os << __x.a() << __sp << __x.b(); @@ -5289,7 +5302,8 @@ const fisher_f_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); __os << __x.m() << __sp << __x.n(); @@ -5388,7 +5402,8 @@ const student_t_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); __os << __x.n(); return __os; } @@ -5586,7 +5601,8 @@ const discrete_distribution<_IT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); size_t __n = __x.__p_.__p_.size(); @@ -5627,8 +5643,10 @@ class param_type { - vector<double> __p_; + typedef typename common_type<double, result_type>::type __area_type; vector<result_type> __b_; + vector<double> __densities_; + vector<__area_type> __areas_; public: typedef piecewise_constant_distribution distribution_type; @@ -5643,10 +5661,10 @@ _UnaryOperation __fw); vector<result_type> intervals() const {return __b_;} - vector<double> densities() const; + vector<double> densities() const {return __densities_;} friend bool operator==(const param_type& __x, const param_type& __y) - {return __x.__p_ == __y.__p_ && __x.__b_ == __y.__b_;} + {return __x.__densities_ == __y.__densities_ && __x.__b_ == __y.__b_;} friend bool operator!=(const param_type& __x, const param_type& __y) {return !(__x == __y);} @@ -5734,29 +5752,27 @@ void piecewise_constant_distribution<_RealType>::param_type::__init() { - if (!__p_.empty()) - { - if (__p_.size() > 1) - { - double __s = _STD::accumulate(__p_.begin(), __p_.end(), 0.0); - for (_STD::vector<double>::iterator __i = __p_.begin(), __e = __p_.end(); - __i < __e; ++__i) - *__i /= __s; - vector<double> __t(__p_.size() - 1); - _STD::partial_sum(__p_.begin(), __p_.end() - 1, __t.begin()); - swap(__p_, __t); - } - else - { - __p_.clear(); - __p_.shrink_to_fit(); - } - } + // __densities_ contains non-normalized areas + __area_type __total_area = _STD::accumulate(__densities_.begin(), + __densities_.end(), + __area_type()); + for (size_t __i = 0; __i < __densities_.size(); ++__i) + __densities_[__i] /= __total_area; + // __densities_ contains normalized areas + __areas_.assign(__densities_.size(), __area_type()); + _STD::partial_sum(__densities_.begin(), __densities_.end() - 1, + __areas_.begin() + 1); + // __areas_ contains partial sums of normalized areas: [0, __densities_ - 1] + __densities_.back() = 1 - __areas_.back(); // correct round off error + for (size_t __i = 0; __i < __densities_.size(); ++__i) + __densities_[__i] /= (__b_[__i+1] - __b_[__i]); + // __densities_ now contains __densities_ } template<class _RealType> piecewise_constant_distribution<_RealType>::param_type::param_type() - : __b_(2) + : __b_(2), + __densities_(1, 1.0) { __b_[1] = 1; } @@ -5772,12 +5788,13 @@ __b_.resize(2); __b_[0] = 0; __b_[1] = 1; + __densities_.assign(1, 1.0); } else { - __p_.reserve(__b_.size() - 1); + __densities_.reserve(__b_.size() - 1); for (size_t __i = 0; __i < __b_.size() - 1; ++__i, ++__fW) - __p_.push_back(*__fW); + __densities_.push_back(*__fW); __init(); } } @@ -5793,12 +5810,13 @@ __b_.resize(2); __b_[0] = 0; __b_[1] = 1; + __densities_.assign(1, 1.0); } else { - __p_.reserve(__b_.size() - 1); + __densities_.reserve(__b_.size() - 1); for (size_t __i = 0; __i < __b_.size() - 1; ++__i) - __p_.push_back(__fw((__b_[__i+1] + __b_[__i])*.5)); + __densities_.push_back(__fw((__b_[__i+1] + __b_[__i])*.5)); __init(); } } @@ -5811,56 +5829,27 @@ { size_t __n = __b_.size() - 1; result_type __d = (__xmax - __xmin) / __n; - __p_.reserve(__n); + __densities_.reserve(__n); for (size_t __i = 0; __i < __n; ++__i) { __b_[__i] = __xmin + __i * __d; - __p_.push_back(__fw(__b_[__i] + __d*.5)); + __densities_.push_back(__fw(__b_[__i] + __d*.5)); } __b_[__n] = __xmax; __init(); } template<class _RealType> -vector<double> -piecewise_constant_distribution<_RealType>::param_type::densities() const -{ - const size_t __n = __b_.size() - 1; - vector<double> __d(__n); - if (__n == 1) - __d[0] = 1/(__b_[1] - __b_[0]); - else - { - __d[0] = __p_[0] / (__b_[1] - __b_[0]); - for (size_t __i = 1; __i < __n - 1; ++__i) - __d[__i] = (__p_[__i] - __p_[__i-1]) / (__b_[__i+1] - __b_[__i]); - __d[__n-1] = (1 - __p_[__n-2]) / (__b_[__n] - __b_[__n-1]); - } - return __d; -}; - - -template<class _RealType> template<class _URNG> _RealType piecewise_constant_distribution<_RealType>::operator()(_URNG& __g, const param_type& __p) { typedef uniform_real_distribution<result_type> _Gen; - if (__p.__b_.size() == 2) - return _Gen(__p.__b_[0], __p.__b_[1])(__g); result_type __u = _Gen()(__g); - const vector<double>& __dd = __p.__p_; - size_t __k = static_cast<size_t>(_STD::upper_bound(__dd.begin(), - __dd.end(), static_cast<double>(__u)) - __dd.begin()); - if (__k == 0) - return static_cast<result_type>(__u * (__p.__b_[1] - __p.__b_[0]) / - __dd[0] + __p.__b_[0]); - __u -= __dd[__k-1]; - if (__k == __dd.size()) - return static_cast<result_type>(__u * (__p.__b_[__k+1] - __p.__b_[__k]) / - (1 - __dd[__k-1]) + __p.__b_[__k]); - return static_cast<result_type>(__u * (__p.__b_[__k+1] - __p.__b_[__k]) / - (__dd[__k] - __dd[__k-1]) + __p.__b_[__k]); + ptrdiff_t __k = _STD::upper_bound(__p.__areas_.begin(), __p.__areas_.end(), + static_cast<double>(__u)) - __p.__areas_.begin() - 1; + return static_cast<result_type>((__u - __p.__areas_[__k]) / __p.__densities_[__k] + + __p.__b_[__k]); } template <class _CharT, class _Traits, class _RT> @@ -5869,17 +5858,22 @@ const piecewise_constant_distribution<_RT>& __x) { __save_flags<_CharT, _Traits> _(__os); - __os.flags(ios_base::dec | ios_base::left); + __os.flags(ios_base::dec | ios_base::left | ios_base::fixed | + ios_base::scientific); _CharT __sp = __os.widen(' '); __os.fill(__sp); - size_t __n = __x.__p_.__p_.size(); + size_t __n = __x.__p_.__b_.size(); __os << __n; for (size_t __i = 0; __i < __n; ++__i) - __os << __sp << __x.__p_.__p_[__i]; - __n = __x.__p_.__b_.size(); + __os << __sp << __x.__p_.__b_[__i]; + __n = __x.__p_.__densities_.size(); __os << __sp << __n; for (size_t __i = 0; __i < __n; ++__i) - __os << __sp << __x.__p_.__b_[__i]; + __os << __sp << __x.__p_.__densities_[__i]; + __n = __x.__p_.__areas_.size(); + __os << __sp << __n; + for (size_t __i = 0; __i < __n; ++__i) + __os << __sp << __x.__p_.__areas_[__i]; return __os; } @@ -5891,21 +5885,27 @@ typedef piecewise_constant_distribution<_RT> _Eng; typedef typename _Eng::result_type result_type; typedef typename _Eng::param_type param_type; + typedef typename param_type::__area_type __area_type; __save_flags<_CharT, _Traits> _(__is); __is.flags(ios_base::dec | ios_base::skipws); size_t __n; __is >> __n; - vector<double> __p(__n); - for (size_t __i = 0; __i < __n; ++__i) - __is >> __p[__i]; - __is >> __n; vector<result_type> __b(__n); for (size_t __i = 0; __i < __n; ++__i) __is >> __b[__i]; + __is >> __n; + vector<double> __densities(__n); + for (size_t __i = 0; __i < __n; ++__i) + __is >> __densities[__i]; + __is >> __n; + vector<__area_type> __areas(__n); + for (size_t __i = 0; __i < __n; ++__i) + __is >> __areas[__i]; if (!__is.fail()) { - swap(__x.__p_.__p_, __p); swap(__x.__p_.__b_, __b); + swap(__x.__p_.__densities_, __densities); + swap(__x.__p_.__areas_, __areas); } return __is; }